﻿// --------------------------------------------------------------------------------------------------------------------
// <copyright file="UseCase.Commands.cs" company="">
//   
// </copyright>
// <summary>
//   The use case.
// </summary>
// --------------------------------------------------------------------------------------------------------------------

namespace Libium.UseCases
{
    using System;
    using System.Collections.Generic;
	using System.Linq;

    /// <summary>
    ///   The use case.
    /// </summary>
    public abstract partial class UseCase
    {
        #region Public Properties

        /// <summary>
        ///   Gets the commands.
        /// </summary>
        public IEnumerable<ICommand> Commands
        {
            get
            {
                return this._commands;
            }
        }

        #endregion

        #region Public Methods and Operators

        /// <summary>
        /// The execute command.
        /// </summary>
        /// <param name="call">
        /// The call. 
        /// </param>
        public virtual void ExecuteCommand(CommandCall call)
        {
            CommandHandlerInfo handlerInfo;
            this._commandHandlers.TryGetValue(call.Command.Id, out handlerInfo);

            if (handlerInfo == null)
            {
                return;
            }

            if (handlerInfo.Phase == CommandHandlePhase.Any || handlerInfo.Phase == call.Phase)
            {
                handlerInfo.Handler(call);
            }
        }

        #endregion

        #region Methods

        /// <summary>
        /// The add command.
        /// </summary>
        /// <param name="text">
        /// The text. 
        /// </param>
        /// <param name="description">
        /// The description. 
        /// </param>
        /// <param name="isModifying">
        /// The is modifying. 
        /// </param>
        /// <returns>
        /// The <see cref="ICommand"/> . 
        /// </returns>
        protected ICommand AddCommand(string text, string description = "", bool isModifying = true)
        {
            var command = new Command(
                new CommandDefinition(Guid.NewGuid(), text, description, isModifying), this, this.Service);
            this._commands.Add(command);
            return command;
        }

        /// <summary>
        /// The add command.
        /// </summary>
        /// <param name="text">
        /// The text. 
        /// </param>
        /// <param name="description">
        /// The description. 
        /// </param>
        /// <param name="isModifying">
        /// The is modifying. 
        /// </param>
        /// <param name="handler">
        /// The handler. 
        /// </param>
        /// <returns>
        /// The <see cref="ICommand"/> . 
        /// </returns>
        protected ICommand AddCommand(string text, string description, bool isModifying, Action<CommandCall> handler)
        {
            var command = this.AddCommand(text, description, isModifying);
            AddCommandHandler(command, handler);
            return command;
        }

        /// <summary>
        /// The add command.
        /// </summary>
        /// <param name="definition">
        /// The definition. 
        /// </param>
        /// <returns>
        /// The <see cref="ICommand"/> . 
        /// </returns>
        protected ICommand AddCommand(CommandDefinition definition)
        {
            var command = new Command(definition, this, this.Service);
            this._commands.Add(command);
            return command;
        }

        /// <summary>
        /// The add command.
        /// </summary>
        /// <param name="definition">
        /// The definition. 
        /// </param>
        /// <param name="handler">
        /// The handler. 
        /// </param>
        /// <returns>
        /// The <see cref="ICommand"/> . 
        /// </returns>
        protected ICommand AddCommand(CommandDefinition definition, Action<CommandCall> handler)
        {
            var command = AddCommand(definition);
            AddCommandHandler(command, handler);
            return command;
        }

		  protected void RemoveCommand(string commantText)
		  {
			  ICommand cmdToRemove = _commands.First(cmd => cmd.Text == commantText);
			  _commands.Remove(cmdToRemove);
		  }

        /// <summary>
        /// The add command handler.
        /// </summary>
        /// <param name="commandId">
        /// The command id. 
        /// </param>
        /// <param name="phase">
        /// The phase. 
        /// </param>
        /// <param name="handler">
        /// The handler. 
        /// </param>
        protected void AddCommandHandler(Guid commandId, CommandHandlePhase phase, Action<CommandCall> handler)
        {
            this._commandHandlers.Add(commandId, new CommandHandlerInfo { Phase = phase, Handler = handler });
        }

        /// <summary>
        /// The add command handler.
        /// </summary>
        /// <param name="commandId">
        /// The command id. 
        /// </param>
        /// <param name="handler">
        /// The handler. 
        /// </param>
        protected void AddCommandHandler(Guid commandId, Action<CommandCall> handler)
        {
            AddCommandHandler(commandId, CommandHandlePhase.Bubble, handler);
        }

        /// <summary>
        /// The add command handler.
        /// </summary>
        /// <param name="command">
        /// The command. 
        /// </param>
        /// <param name="phase">
        /// The phase. 
        /// </param>
        /// <param name="handler">
        /// The handler. 
        /// </param>
        protected void AddCommandHandler(ICommand command, CommandHandlePhase phase, Action<CommandCall> handler)
        {
            AddCommandHandler(command.Id, phase, handler);
        }

        /// <summary>
        /// The add command handler.
        /// </summary>
        /// <param name="command">
        /// The command. 
        /// </param>
        /// <param name="handler">
        /// The handler. 
        /// </param>
        protected void AddCommandHandler(ICommand command, Action<CommandCall> handler)
        {
            AddCommandHandler(command, CommandHandlePhase.Bubble, handler);
        }

        /// <summary>
        /// The add command handler.
        /// </summary>
        /// <param name="definition">
        /// The definition. 
        /// </param>
        /// <param name="phase">
        /// The phase. 
        /// </param>
        /// <param name="handler">
        /// The handler. 
        /// </param>
        protected void AddCommandHandler(
            CommandDefinition definition, CommandHandlePhase phase, Action<CommandCall> handler)
        {
            AddCommandHandler(definition.Id, phase, handler);
        }

        /// <summary>
        /// The add command handler.
        /// </summary>
        /// <param name="definition">
        /// The definition. 
        /// </param>
        /// <param name="handler">
        /// The handler. 
        /// </param>
        protected void AddCommandHandler(CommandDefinition definition, Action<CommandCall> handler)
        {
            AddCommandHandler(definition, CommandHandlePhase.Bubble, handler);
        }

        #endregion

        /// <summary>
        ///   The command handler info.
        /// </summary>
        private class CommandHandlerInfo
        {
            #region Fields

            /// <summary>
            ///   The handler.
            /// </summary>
            public Action<CommandCall> Handler;

            /// <summary>
            ///   The phase.
            /// </summary>
            public CommandHandlePhase Phase;

            #endregion
        }
    }
}